/*
 * @FileName: app_fsm.c
 * @Author: GreyQiu qiushaogui@aikosolar.com
 * @Date: 2023-07-17 15:53:58
 * @LastEditors: GreyQiu qiushaogui@aikosolar.com
 * @LastEditTime: 2023-09-25 10:40:46
 * @Description: 
 * 
 * Copyright (c) 2023, All Rights Reserved. 
 */

#include "app_fsm.h"
#include "app_fault.h"
#include "app_analog.h"
#include "app_mppt.h"
#include "fsm.h"
#include "bsp.h"
#include "dev_info.h"
#include "loop.h"
#include "mbreg.h"

#define FSM_RUN_TS 1 // 状态机运行周期1ms
#define RAMP_SLOPE 0.28f // 电压上升斜率

uint8_t g_aging_flag = 0;

fsm_t fsm_buck;
powerCtrl_t pwrCtrlBits;
uint16_t powerMode = 0;

static void act_ready_ramp(void);
static void act_ramp_normal(void);
static void act_ramp_run(void);
static void act_normal_run(void);
static void act_jump2shutdown(void);

static event_t chk_init(void);
static event_t chk_ready(void);
static event_t chk_ramp(void);
static event_t chk_normal(void);
static event_t chk_shutdown(void);
static event_t chk_hiccup(void);

float goalMax = 20.0f;
/**
 * @description: 事件驱动状态跳转 状态跳转表
 */
static uint8_t sta_tbl[STATE_NUM][EVENT_NUM] =
{
    /*EVENT_NONE*/      /*EVENT_NORMAL*/    /*EVENT_ABNORMAL*/
    {STATE_INIT,        STATE_READY,        STATE_SHUTDOWN}, // STATE_INIT
    {STATE_READY,       STATE_RAMPUP,       STATE_SHUTDOWN}, // STATE_READY
    {STATE_RAMPUP,      STATE_NORMAL,       STATE_SHUTDOWN}, // STATE_RAMPUP
    {STATE_NORMAL,      STATE_HICCUP,       STATE_SHUTDOWN}, // STATE_NORMAL
    {STATE_SHUTDOWN,    STATE_READY,        STATE_SHUTDOWN},  // STATE_SHUTDOWN
    {STATE_HICCUP,      STATE_RAMPUP,       STATE_SHUTDOWN},  // STATE_HICCUP
};

/**
 * @description: 事件驱动执行动作 动作执行表
 */
static sta_action_t act_tbl[STATE_NUM][EVENT_NUM] =
{
    /*EVENT_NONE*/      /*EVENT_NORMAL*/    /*EVENT_ABNORMAL*/
    {NULL,              NULL,               NULL}, // STATE_INIT
    {NULL,              act_ready_ramp,     act_jump2shutdown}, // STATE_READY
    {act_ramp_run,      act_ramp_normal,    act_jump2shutdown}, // STATE_RAMPUP
    {act_normal_run,    act_jump2shutdown,  act_jump2shutdown}, // STATE_NORMAL
    {NULL,              NULL,               NULL},  // STATE_SHUTDOWN
    {NULL,              act_ready_ramp,     act_jump2shutdown},  // STATE_HICCUP
};

/**
 * @description: 每个状态对应的事件检查函数
 */
static sta_check_t check_tbl[STATE_NUM] =
{
    chk_init,       // STATE_INIT
    chk_ready,      // STATE_READY
    chk_ramp,       // STATE_RAMPUP
    chk_normal,     // STATE_NORMAL
    chk_shutdown,   // STATE_SHUTDOWN
    chk_hiccup,     // STATE_HICCUP
};


// ready跳转至ramp的执行动作
static void act_ready_ramp(void)
{
    // 环路清0
    vout_loop_clear();
    iout_loop_clear();

    // 设定环路基准初始值
    vout_loop_ref_set(analog_real_filter(ANALOG_ID_VOUT));
//    vout_loop_ref_set(0.0f);
    iout_loop_ref_set(0.0f);

    // 使能PWM输出

    bsp_pwm_hb1_duty(0);
    bsp_pwm_hb2_duty(0);

    bsp_pwm_output_enable();
    loop_enable(); // 环路使能
}

// ready跳转至ramp的执行动作
static void act_ramp_normal(void)
{

}
float vmax = -1.0f; // 避免开启软起无效
// 逐步展开电压环基准
static void act_ramp_run(void)
{
    float goal1 = vout_loop_ref_get();

    vout_loop.Ymax = loop_status.Iset;

    if (pwr_dir == 2) {
        vmax = loop_status.Vset;
    } else {
        vmax = loop_status.VsetDischarge;
    }
    goal1 += RAMP_SLOPE;
    if (goal1 > vmax)
    {
        goal1 = vmax;
    }
    vout_loop_ref_set(goal1);
}

static void act_normal_run(void)
{
    float vtmp;

    vout_loop.Ymax = loop_status.Iset;

    if (pwr_dir == 2) {
        vout_loop.ref = loop_status.Vset;
    } else {
        vout_loop.ref = loop_status.VsetDischarge;
    }

    if (analog_real_filter(ANALOG_ID_IOUT) > 1.6f) {
        analog_tbl[ANALOG_ID_IIN].k1 =  0.0001f * fsbb_info.factor[FACTOR_IDX_IIN].k;
        analog_tbl[ANALOG_ID_IIN].b1 =  0.0001f * fsbb_info.factor[FACTOR_IDX_IIN].b;
        analog_tbl[ANALOG_ID_IOUT].k1 =  0.0001f * fsbb_info.factor[FACTOR_IDX_IOUT].k;
        analog_tbl[ANALOG_ID_IOUT].b1 =  0.0001f * fsbb_info.factor[FACTOR_IDX_IOUT].b;
    } else if (analog_real_filter(ANALOG_ID_IOUT) < 1.3f) {
        analog_tbl[ANALOG_ID_IIN].k1 =  0.0001f * fsbb_info.factor[FACTOR_IDX_IIN_L].k;
        analog_tbl[ANALOG_ID_IIN].b1 =  0.0001f * fsbb_info.factor[FACTOR_IDX_IIN_L].b;
        analog_tbl[ANALOG_ID_IOUT].k1 =  0.0001f * fsbb_info.factor[FACTOR_IDX_IOUT_L].k;
        analog_tbl[ANALOG_ID_IOUT].b1 =  0.0001f * fsbb_info.factor[FACTOR_IDX_IOUT_L].b;
    }
}

static void act_jump2shutdown(void)
{
    // 使能PWM输出
    bsp_pwm_output_disable();
    bsp_pwm_hb1_duty(0);
    bsp_pwm_hb2_duty(0);

    loop_disable(); // 环路禁止



    log_debug("fault happend ---> fault = 0x%02x  \n\n", app_fault_get_bits());
}


static event_t chk_init(void)
{
    // 首次开机等待3秒
    if (fsm_is_timeout(&fsm_buck, 3000)) { // 等待3000ms
        fsm_time_reset(&fsm_buck);
        return EVENT_NORMAL;
    }

    return EVENT_NONE;
}


static event_t chk_ready(void)
{
    if (app_fault_get_bits() != 0 || pwrCtrlBits.bit.pwr_mode == OFF_MODE) { // 检查是否有故障
        return EVENT_ABNORMAL;
    }

    // 没有故障并且维持2秒，则可以返回正常事件
    if (fsm_is_timeout(&fsm_buck, 2000)) { // 等待2000ms
        fsm_time_reset(&fsm_buck);
        return EVENT_NORMAL;
    }

    return EVENT_NONE;
}

static event_t chk_ramp(void)
{

    if (app_fault_get_bits() != 0 || pwrCtrlBits.bit.pwr_mode == OFF_MODE) { // 检查是否有故障
        return EVENT_ABNORMAL;
    }

    // 判断环路基准达到目标值,跳转至NORMAL状态
    if (vout_loop_ref_get() == vmax) {
        return EVENT_NORMAL;
    }
    return EVENT_NONE;
}

static event_t chk_normal(void)
{
    if (app_fault_get_bits() != 0 || pwrCtrlBits.bit.pwr_mode == OFF_MODE) { // 检查是否有故障
        fsm_time_reset(&fsm_buck);
        return EVENT_ABNORMAL;
    }

    return EVENT_NONE;
}

static event_t chk_shutdown(void)
{
    if (app_fault_get_bits() != 0 || pwrCtrlBits.bit.pwr_mode == OFF_MODE) { // 检查是否有故障
        return EVENT_ABNORMAL;
    }
    fsm_time_reset(&fsm_buck);
    
    return EVENT_NORMAL;
}

static event_t chk_hiccup(void)
{
    if (app_fault_get_bits() != 0 || pwrCtrlBits.bit.pwr_mode == OFF_MODE) { // 检查是否有故障
        return EVENT_ABNORMAL;
    }

    if (fsm_is_timeout(&fsm_buck, 50)) { // 等待200ms
        fsm_time_reset(&fsm_buck);
        return EVENT_NORMAL;
    }

    return EVENT_NONE;
}

void app_fsm_init(void)
{
    fsm_config(&fsm_buck, sta_tbl, act_tbl, check_tbl);
    fsm_buck.sta_cur = STATE_INIT;
    fsm_buck.time = 0;

    pwrCtrlBits.bit.fb_enable = 0;
    pwrCtrlBits.bit.pwr_mode = OFF_MODE;
    pwrCtrlBits.bit.reseverd = 0;
}

void app_fsm_run(void)
{
    if (pwrCtrlBits.word != 0 && mbHoldingReg[MB_REG_CONTROL] != pwrCtrlBits.word) {
        mbHoldingReg[MB_REG_CONTROL] = 0;
    }
    pwrCtrlBits.word = mbHoldingReg[MB_REG_CONTROL];
    pwr_dir = pwrCtrlBits.bit.pwr_mode;
    fsm_handler(&fsm_buck);
}

uint8_t fsm_get_status(void)
{
    return fsm_buck.sta_cur;
}
